package com.sl.core.engine.plugin;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FastByteArrayOutputStream;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.sl.core.engine.plugin.domain.PluginDecorate;
import com.sl.core.engine.plugin.loader.ProcessPluginLoader;
import com.sl.core.engine.plugin.loader.impl.VmProcessPluginLoader;
import lombok.SneakyThrows;
import org.apache.commons.compress.utils.Lists;
import org.springframework.core.io.UrlResource;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.*;

public class ProcessPluginLoaderManager {

    public static ProcessPluginLoaderManager INSTANCE = new ProcessPluginLoaderManager();

    private List<ProcessPluginLoader> processPluginLoaders = Lists.newArrayList();

    public static final String LATEST_TAG="latest";

    public void registry(ProcessPluginLoader processPluginLoader) {
        this.processPluginLoaders.add(processPluginLoader);
    }

    public ProcessPluginLoaderManager() {
        this.registry(VmProcessPluginLoader.INSTANCE);

    }


    public PluginDecorate matchPlugin(String code) {
        //获取最新版本
        return this.matchPlugin(null,code, null);
    }

    public List<PluginDecorate> matchPluginList(String code) {
        List<PluginDecorate> res = Lists.newArrayList();
        for (ProcessPluginLoader processPluginLoader : processPluginLoaders) {
            List<PluginDecorate> pluginDecorates = processPluginLoader.get(code);
            if (CollUtil.isNotEmpty(pluginDecorates)) {
                res.addAll(pluginDecorates);
            }
        }
        //获取最新版本
        return res;
    }

    public PluginDecorate matchPlugin(String orgId,String code, String version) {
        if (StrUtil.equals(version, LATEST_TAG)) {
            version = "";
        }
        PluginDecorate pluginDecorate = null;
        for (ProcessPluginLoader processPluginLoader : processPluginLoaders) {
            pluginDecorate = processPluginLoader.get(orgId,code, version);
            if (ObjectUtil.isNotNull(pluginDecorate)) {
                break;
            }
        }
        return pluginDecorate;
    }

    public Map<String, List<PluginDecorate>> loader() {
        Map<String, List<PluginDecorate>> res = new LinkedHashMap<>();
        for (ProcessPluginLoader processPluginLoader : processPluginLoaders) {
            Map<String, List<PluginDecorate>> loader = processPluginLoader.loader();
            if (MapUtil.isNotEmpty(loader)) {
                res.putAll(loader);
            }
        }
        return res;
    }


    public byte[] getResource(String orgId,String code, String version, String resourceName) {

        //根据code找到插件
        PluginDecorate pluginDecorate = this.matchPlugin(orgId,code, version);
        if (ObjectUtil.isNull(pluginDecorate)) {
            return null;
        }
        byte[] resource = getResource(pluginDecorate.getClassLoader(), pluginDecorate.getFileUrl(), resourceName);
        if (ObjectUtil.isNull(resource)) {
            resource = getResourceByIndex(pluginDecorate.getClassLoader(), pluginDecorate.getFileUrl(), resourceName);
        }
        return resource;
    }


    @SneakyThrows
    private byte[] getResource(ClassLoader classLoader, String fileUrl, String resourceName) {
        //开始自动查找
        //找到内容
        Enumeration<URL> urls = classLoader.getResources("plugin." + resourceName);

        while (urls.hasMoreElements()) {
            URL url = urls.nextElement();
            UrlResource resource = new UrlResource(url);
            String s = url.toString();

            String matchUrlSource = StrUtil.subBefore(fileUrl, "/", true);
            String matchUrlTarget = StrUtil.subBefore(s, "/", true);

            if (StrUtil.equalsIgnoreCase(matchUrlTarget, matchUrlSource)) {
                InputStream inputStream = resource.getInputStream();
                FastByteArrayOutputStream read = IoUtil.read(inputStream);
                return read.toByteArray();
            }
        }
        return null;

    }

    @SneakyThrows
    private byte[] getResourceByIndex(ClassLoader classLoader, String fileUrl, String resourceName) {
        //开始自动查找
        //找到内容
        Enumeration<URL> urls = classLoader.getResources("index." + resourceName);

        while (urls.hasMoreElements()) {
            URL url = urls.nextElement();
            UrlResource resource = new UrlResource(url);
            String s = url.toString();

            String matchUrlSource = StrUtil.subBefore(fileUrl, "/", true);
            String matchUrlTarget = StrUtil.subBefore(s, "/", true);

            if (StrUtil.equalsIgnoreCase(matchUrlTarget, matchUrlSource)) {
                InputStream inputStream = resource.getInputStream();
                FastByteArrayOutputStream read = IoUtil.read(inputStream);
                return read.toByteArray();
            }
        }
        return null;

    }

    public ByteArrayInputStream getResourceCode(String orgId,String pluginCode, String pluginVersion) {
        for (ProcessPluginLoader processPluginLoader : processPluginLoaders) {
            ByteArrayInputStream resourceCode = processPluginLoader.getResourceCode(orgId,pluginCode, pluginVersion);
            if (ObjectUtil.isNotNull(resourceCode)) {
                return resourceCode;
            }
        }
        return null;
    }
}
